#ifndef STATUS_H_
#define STATUS_H_

#include <wx/string.h>
#include <wx/log.h>
#include "database/DBType.h"

namespace Impp{

enum PrivacySetting{
	PRICACY_INVALID = 0,
	PRICACY_ALLOW_ALL = 1, //If 1, then allow all users to see you.
	PRICACY_BLOCK_ALL = 2, //If 2, then block all users from seeing you.
	PRICACY_ALLOW_ONLY_PERMITLIST = 3, //If 3, then allow only the users in the permit list.
	PRICACY_BLOCK_ONLY_DENYLIST = 4, //If 4, then block only the users in the deny list.
	PRICACY_ALLOW_ONLY_BUDDYLIST= 5  //If 5 then allow only users on your buddy list.
};



enum Statusflag{
	ONLINE 		= 0x0001,
	FREE4CHAT	= 0x0002,
	AWAY		= 0x0004,
	OCCUPIED  	= 0x0008,
	DND 		= 0x0010,
	NA			= 0x0020,
	INVISIBLE	= 0x2000,
	UNKNOWN		= 0x4000,
	OFFLINE 	= 0x8000
};

enum StatusAndMsgFlag{
	STATUS_AND_MSG_FLAG_NO  = 0x0000,
	STATUS_AND_MSG_FLAG_NEW = 0x0001
};


class Status{

private:
	int/*<Statusflag>*/ mask;

public:
	Status() : mask(OFFLINE){}

	Status(const int/*<Statusflag>*/ & mask) : mask(mask){}

	Status(const Statusflag & flag){
		mask=flag;
	}


	inline Status& operator=(const Statusflag & flag){
		mask=flag;
		return *this;
	}

	inline bool operator==(const Statusflag & flag) const{
		return (mask & flag) != 0;
	}

	inline bool operator!=(const Statusflag & flag) const{
		return (mask & flag) == 0;
	}

	inline bool operator==(const Status & status) const{
		return this->mask == status.mask;
	}

	inline bool operator!=(const Status & status) const{
		return this->mask != status.mask;
	}

	inline void setFlag(const int/*<Statusflag>*/ & flag){
		mask |= flag;
	}

	inline void clearFlag(const int/*<Statusflag>*/ & flag){
		mask &= ~flag;
	}

	inline void clearExtraStatus(){
		mask &= 0x0000FFFF;
	}


	inline void setExtraStatus(int xstatus){
		clearExtraStatus();
		mask |= (xstatus << 16);
	}

	inline int getExtraStatus() const{
		return (mask >> 16) & 0x0000FFFF;
	}

	inline bool operator< (const Status & other) const{
		if(*this == UNKNOWN && *this != INVISIBLE){
			return false;
		}
		if(other == UNKNOWN && other != INVISIBLE){
			return true;
		}

		Status otherTmp = other;
		Status thisTmp(*this);

		otherTmp.clearFlag(INVISIBLE);
		thisTmp.clearFlag(INVISIBLE);

		otherTmp.clearExtraStatus();
		thisTmp.clearExtraStatus();

		return thisTmp.mask < otherTmp.mask;
	}

	inline int getMask() const{
		return mask;
	}

	inline void logMask() const{
		wxLogDebug(wxT("Mask %X"), getMask());
	}

};

class StatusAndMsg{
public:
	db_id id;
	Status status;
	wxString title;
	wxString msg;
	int flags;
	db_id accountId;
};

wxString statusToString(const Status & status);

}

#endif /*STATUS_H_*/
